#include <head.h>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

// 创建一个信号量，返回信号量的ID
int create_semaphore(key_t key, int initial_value) 
{
    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1) 
    {
        perror("semget");
        exit(1);
    }

    union semun arg;
    arg.val = initial_value;
    if (semctl(semid, 0, SETVAL, arg) == -1) 
    {
        perror("semctl");
        exit(1);
    }

    return semid;
}

// 等待信号量，将信号量值减1，如果信号量为0则阻塞
void semaphore_wait(int semid) 
{
    struct sembuf op;
    op.sem_num = 0;
    op.sem_op = -1;
    op.sem_flg = 0;

    if (semop(semid, &op, 1) == -1) 
    {
        perror("semop");
        exit(1);
    }
}

// 发送信号量，将信号量值加1，如果有阻塞的进程则唤醒
void semaphore_signal(int semid) 
{
    struct sembuf op;
    op.sem_num = 0;
    op.sem_op = 1;
    op.sem_flg = 0;

    if (semop(semid, &op, 1) == -1) 
    {
        perror("semop");
        exit(1);
    }
}

// 删除信号量
void delete_semaphore(int semid) 
{
    if (semctl(semid, 0, IPC_RMID) == -1) 
    {
        perror("semctl");
        exit(1);
    }
}

int main(int argc, char const *argv[]) 
{
    key_t key = ftok(".", 's'); // 创建一个唯一的key，这里使用当前目录和字符's'
    int semid = create_semaphore(key, 1); // 创建一个信号量，初始值为1

    // 等待信号量
    printf("等待信号量...\n");
    sleep(2);
    semaphore_wait(semid);
    printf("信号量已释放，继续执行...\n");
    sleep(3);

    // 发送信号量
    printf("发送信号量...\n");
    sleep(2);
    semaphore_signal(semid);
    printf("信号量已发送，其他进程可以继续执行...\n");
    sleep(3);

    // 删除信号量
    delete_semaphore(semid);

    return 0;
}